#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include "../../src/hashtable/lockfree_hashtable.h"

#define NUM_THREADS 4
#define OPS_PER_THREAD 100000
#define BUCKET_COUNT 997  // 质数
#define KEY_RANGE 10000

atomic_int ops_count = 0;

// 简单的字符串哈希函数
size_t str_hash(const void* key) {
    const char* str = (const char*)key;
    size_t hash = 5381;
    int c;
    while ((c = *str++))
        hash = ((hash << 5) + hash) + c;
    return hash;
}

// 字符串比较函数
bool str_equals(const void* key1, const void* key2) {
    return strcmp((const char*)key1, (const char*)key2) == 0;
}

// 生成随机字符串键
char* generate_key(int num) {
    char* key = malloc(16);
    snprintf(key, 16, "key-%d", num);
    return key;
}

void* worker(void* arg) {
    hashtable_t* table = (hashtable_t*)arg;
    
    for (int i = 0; i < OPS_PER_THREAD; i++) {
        int op = rand() % 3;  // 0: put, 1: get, 2: remove
        int key_num = rand() % KEY_RANGE;
        char* key = generate_key(key_num);
        
        switch (op) {
            case 0: {  // put
                char* value = strdup(key);
                if (hashtable_put(table, key, value)) {
                    atomic_fetch_add(&ops_count, 1, memory_order_relaxed);
                } else {
                    free(key);
                    free(value);
                }
                break;
            }
            case 1: {  // get
                void* value = hashtable_get(table, key);
                if (value) {
                    atomic_fetch_add(&ops_count, 1, memory_order_relaxed);
                }
                free(key);
                break;
            }
            case 2: {  // remove
                if (hashtable_remove(table, key)) {
                    atomic_fetch_add(&ops_count, 1, memory_order_relaxed);
                }
                free(key);
                break;
            }
        }
    }
    return NULL;
}

int main() {
    hashtable_t table;
    pthread_t threads[NUM_THREADS];
    struct timespec start, end;
    
    // 初始化哈希表
    if (!hashtable_init(&table, BUCKET_COUNT, str_hash, str_equals)) {
        printf("Failed to initialize hashtable\n");
        return 1;
    }
    
    // 记录开始时间
    clock_gettime(CLOCK_MONOTONIC, &start);
    
    // 创建线程
    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_create(&threads[i], NULL, worker, &table);
    }
    
    // 等待所有线程完成
    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }
    
    // 记录结束时间
    clock_gettime(CLOCK_MONOTONIC, &end);
    
    double time_spent = (end.tv_sec - start.tv_sec) +
                       (end.tv_nsec - start.tv_nsec) / 1e9;
    
    printf("Time spent: %.2f seconds\n", time_spent);
    printf("Operations per second: %.2f\n", 
           atomic_load(&ops_count, memory_order_relaxed) / time_spent);
    printf("Final table size: %zu\n", hashtable_size(&table));
    
    // 清理哈希表
    hashtable_destroy(&table);
    
    return 0;
} 